﻿
namespace TransportAnalizer_2._0.ViewModels
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using System.Windows.Input;
    using TransportAnalizer.HelpClasses;
    using Model;

    /// <summary>
    /// Main application view-model.
    /// </summary>
    public class NodeTypeViewModel : ViewModel
    {
        private readonly INodeTypeBusinessContext context;
        private NodeType selectedNodeType;

        /// <summary>
        /// Initializes a new instance of the <see cref="NodeTypeViewModel"/> class.
        /// </summary>
        public NodeTypeViewModel()
            : this(new BusinessContextFactory())
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="NodeTypeViewModel"/> class.
        /// </summary>
        /// <param name="context">The existing <see cref="BusinessContextFactory"/> instnace the view-model will use.</param>
        public NodeTypeViewModel(IBusinessContextFactory factory)
        {
            NodeTypes = new ObservableCollection<NodeType>();
            this.context = factory.GetNodeTypeBusinessContext;
        }

        /// <summary>
        /// Gets a value indicating whether <see cref="SelectedNodeType"/> is not null.
        /// </summary>
        public bool CanModify
        {
            get
            {
                return SelectedNodeType != null;
            }
        }

        /// <summary>
        /// Gets the collection of nodeType loaded from the data store.
        /// </summary>
        public ICollection<NodeType> NodeTypes
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets or sets the current selected <see cref="NodeType"/>.
        /// </summary>
        public NodeType SelectedNodeType
        {
            get
            {
                return selectedNodeType;
            }
            set
            {
                selectedNodeType = value;
                NotifyPropertyChanged();
                // ReSharper disable once ExplicitCallerInfoArgument
                NotifyPropertyChanged("CanModify");
            }
        }

        /// <summary>
        /// Gets a value indicating whether the view model is valid.
        /// </summary>
        /// <remarks>
        /// You will notice that in this iteration of the demo project there isn't any actual validation happening. This
        /// is because the wiring into the CommandManager.RequerySuggested in ActionCommand was removed because it is not the
        /// proper way to do commanding. It has unexpected behavior and severe performance implications, and should never be
        /// done.
        /// 
        /// To enable this again, we will need to implement another view-model or use the facade pattern in place of using the
        /// customer entity directly so that we can implement INotifyPropertyChanged and execute ActionCommand.CanExecute(object)
        /// when necessary, ultimately updating the commanding system, which will re-enable the enabling/disabling of UI elements
        /// based on the return value.
        /// 
        /// This will be covered more in-depth in a later session.
        /// </remarks>
        public bool IsValid
        {
            get
            {
                return SelectedNodeType == null ||
                       (
                           !String.IsNullOrWhiteSpace(SelectedNodeType.Name) &&
                           !(SelectedNodeType.Description==null)
                       );
            }
        }

        /// <summary>
        /// Gets the command that invokes the retreival of a list of <see cref="NodeType"/> entities.
        /// </summary>
        public ICommand GetNodeTypeListCommand
        {
            get
            {
                return new ActionCommand(p => GetNodeTypeList());
            }
        }

        /// <summary>
        /// Gets the command that invokes the creation of a new <see cref="NodeType"/>.
        /// </summary>
        public ICommand AddCommand
        {
            get
            {
                return new ActionCommand(p => AddNodeType(),
                                         p => IsValid);
            }
        }

        /// <summary>
        /// Gets the command that invokes the deletion of the <see cref="SelectedNodeType"/>.
        /// </summary>
        public ICommand DeleteCommand
        {
            get
            {
                return new ActionCommand(p => DeleteNodeType());
            }
        }

        /// <summary>
        /// Gets the command that invokes an update of the <see cref="SelectedNodeType"/>.
        /// </summary>
        public ICommand UpdateCommand
        {
            get
            {
                return new ActionCommand(p => SaveNodeType(),
                                         p => IsValid);
            }
        }

        private void GetNodeTypeList()
        {
            NodeTypes.Clear();
            SelectedNodeType = null;

            foreach (var nodeType in context.GetNodeTypeList())
                NodeTypes.Add(nodeType);
        }

        private void AddNodeType()
        {
          
                var nodeType = new NodeType
                               {
                                   Name = "New",
                                   Description="New description",
                                   Passage=0,
                                   Regulation=RegulationType.NoRegulation
                               };

                try
                {
                    context.CreateNodeType(nodeType);
                }
                catch (Exception ex)
                {
                    // TODO: In later session, cover error handling
                    return;
                }

                NodeTypes.Add(nodeType);
            
        }

        private void SaveNodeType()
        {
            context.UpdateNodeType(SelectedNodeType);
        }

        private void DeleteNodeType()
        {
            context.DeleteNodeType(SelectedNodeType);
            NodeTypes.Remove(SelectedNodeType);
            SelectedNodeType = null;
        }
    }

}